package inference.traffic;

import java.awt.Color;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import rddl.State;
import rddl.viz.BlockDisplay;
import util.Pair;

public class TrafficDisplay implements TrafficViz {

	private int _nRows;
	private int _nCols;
	private int _wingSize;
	private int _blockSize;

	public BlockDisplay _bd = null;
	public int _nTimeDelay = 0;
	private int _xsize;
	private int _ysize;
	private Set<Pair<Integer, Integer>> _prevOccupado = new HashSet<Pair<Integer, Integer>>();

//	private static Pair<Integer, Integer> _temp
//	= new Pair<Integer, Integer>(Integer.MIN_VALUE, Integer.MIN_VALUE);

	private static String LEFT_ARROW = "\u2190";
	private static String RIGHT_ARROW = "\u2192";
	private static String UP_ARROW = "\u2191";
	private static String DOWN_ARROW = "\u2193";

	public TrafficDisplay(int time_delay_per_frame ){
		_nTimeDelay = time_delay_per_frame; // in milliseconds
	}

	public void display(TrafficState s) {

		if( _bd == null ){

			_nRows = s.get_nRows();
			_nCols = s.get_nCols();

			_blockSize = s.get_nBlockSize();

			_wingSize = s.get_nWingSize();

			_xsize = 1 + _nRows + ( _nRows - 1 ) * _blockSize + 2*_wingSize;
			_ysize = 1 + _nCols + ( _nCols - 1 ) * _blockSize + 2*_wingSize;

			_bd = new BlockDisplay("Traffic simulation", "" + _xsize + " X " + _ysize, _xsize, _ysize);

			for( int j = _wingSize; j < _wingSize + (_nRows-1)*_blockSize + _nRows; j += _blockSize+1 ){

				Pair<Boolean, Boolean> x = s.get_xion_dirxn(_wingSize, j);

				String text = x._o1 ? LEFT_ARROW : RIGHT_ARROW;
				
				setCell( toGraphicsCoord( _xsize-1, j) , Color.black, text);

			}

			for( int i = _wingSize; i < _wingSize + (_nCols-1)*_blockSize + _nCols; i += _blockSize+1 ){

				Pair<Boolean, Boolean> x = s.get_xion_dirxn(i, _wingSize);

				String text = x._o2 ? DOWN_ARROW : UP_ARROW;

				setCell( toGraphicsCoord( i, _ysize-1 ), Color.black, text);

			}

			_bd.repaint();

		}

		Map<Pair<Integer, Integer>, Pair<Boolean, Boolean>> lights = s.get_lights();


		clearOld( );

		Set<Pair<Integer, Integer>> occupado = s.getOccupiedCells();
		_prevOccupado.clear();

		for( Pair<Integer, Integer> cell : occupado ){
			Pair<Integer, Integer> graphCoords = toGraphicsCoord( cell );
			try {
				_prevOccupado.add( (Pair<Integer, Integer>) graphCoords.clone() );
			} catch (CloneNotSupportedException e) {
				e.printStackTrace();
			}

			setCell( graphCoords , Color.blue, "o");
		}

		for( Map.Entry<Pair<Integer, Integer>, Pair<Boolean, Boolean>> entry : lights.entrySet() ){

			Pair<Integer, Integer> coord = entry.getKey();

			Pair<Boolean, Boolean> lightState = entry.getValue();

			Pair<Boolean, Boolean> xion_dirxn = s.get_xion_dirxn(coord._o1, coord._o2);

			Color col = null;

			if( occupado.contains(coord) ){
				col = Color.yellow;
			}else if( lightState._o1 && lightState._o2 ){
				col = Color.red;
			}else if( !lightState._o1 && !lightState._o2 ){
				col = Color.red;
			}else{
				col = Color.green;
			}

			String text = null;

			if( lightState._o1 && !lightState._o2 ){
				if( xion_dirxn._o1 ){
					text = LEFT_ARROW;
				}else{
					text = RIGHT_ARROW;
				}
			}else if( !lightState._o1 && lightState._o2 ){
				if( xion_dirxn._o2 ){
					text = DOWN_ARROW;
				}else{
					text = UP_ARROW;
				}
			}else if( lightState._o1 && lightState._o2 ){
				text = "X";
			}else{
				text = "X";
			}

			setCell( toGraphicsCoord( coord ) , col, text );

		}


		_bd.repaint();


		try {
			Thread.currentThread().sleep(_nTimeDelay);
		} catch (InterruptedException e) {
		}

	}

	private Pair<Integer, Integer> toGraphicsCoord(int x, int y) {
//		_temp._o1 = x;
//		_temp._o2 = y;
		return toGraphicsCoord(new Pair<Integer	, Integer>(x, y));
	}

	private void clearOld() {

		if( _prevOccupado != null ){
			for( Pair<Integer, Integer> cell : _prevOccupado ){
				setCell(cell, Color.black, "-");
			}
		}

	}

	private void setCell(int x, int y, Color col, String text) {
//		_temp._o1 = x;
//		_temp._o2 = y;
		setCell(new Pair<Integer, Integer>(x,y), col, text);
	}

	private void setCell( Pair<Integer, Integer> graphCoord, Color col, String text ){
		_bd.setCell(graphCoord._o1, graphCoord._o2, col, text);
	}

	private Pair<Integer, Integer> toGraphicsCoord(Pair<Integer, Integer> cell) {
		return new Pair<Integer, Integer>( _ysize-cell._o2-1, cell._o1); 
	}


}
